/**************************************************************************************************
	$Header: /pub/cvsroot/mydns/src/mydns/cache.h,v 1.22 2003/03/25 06:38:23 bboy Exp $

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#ifndef _CACHE_H
#define _CACHE_H

/* The actual number of slots specified for `nodes' is the limit multiplied by this number.
	A higher value will yield greater speed (due to fewer collisions) but will use more memory. */
#define	CACHE_SLOT_MULTIPLIER	3

/* Undefine this for less cache info with SIGUSR1 (miniscule speed increase when SIGUSR1'ed) */
#define	EXTENDED_CACHE_STATUS


/* Hash type results, from a P3-850; tables flushed+sync before 1,000,000 questions */
/* 	Original: 39.30 / 19.71 / 3:18.34 / 29% -- 5,051 q/s --  4,637 collisions 	*/
/* 	Rotating: 38.62 / 20.09 / 3:24.18 / 28% -- 4,902 q/s --  5,916 collisions 	*/
/*		Additive: 48.35 / 19.64 / 3:24.61 / 33% -- 4,902 q/s -- 15,183 collisions	*/ 


/* Hash types */
#define	ORIGINAL_HASH	0					/* Original hash (size=prime) */
#define	ADDITIVE_HASH	1					/* Additive hash (size=prime) */
#define	ROTATING_HASH	2					/* Rotating hash (size=power of two) */

#ifndef	HASH_TYPE
#define	HASH_TYPE	ORIGINAL_HASH		/* Default hash type */
#endif


typedef struct _cnode						/* A cache node */
{
	uint32_t		hash;							/* Hash value, for lookup when deleting nodes */
	uint32_t		zone;							/* Zone for record */
	dns_qtype_t	type;							/* Record type */
	char			name[DNS_MAXPACKETLEN_UDP+1];	/* The name to look up */
	size_t		namelen;						/* strlen(name) */
	void			*data;						/* SOA or RR record or reply data (depending on `type') */
	size_t		datalen;						/* Length of data (reply cache only) */
	time_t		expire;						/* Time after which this node should expire */

	struct _cnode *next_node;				/* Pointer to next node in bucket */
	struct _cnode *mru_prev, *mru_next;	/* Pointer to next/prev node in MRU/LRU list */
} CNODE;


typedef struct _cache						/* A cache */
{
	size_t		limit;						/* Max number of nodes allowed (via `cache-size') */
	size_t		count;						/* Number of used nodes in the cache */

	time_t		expire;						/* Expiration seconds for cached items */

	uint32_t		questions;					/* Total number of questions */
	uint32_t		hits, misses;				/* Total number of hits/misses for the cache */
	uint32_t		in, out;						/* Cache entries in and out */
	uint32_t		expired, removed;			/* Cache entries expired and removed */

	uint32_t		slots;						/* Number of slots in `nodes' array */
#if (HASH_TYPE == ROTATING_HASH)
	uint32_t		mask;							/* Hash mask (certain types only) */
#endif
	CNODE			**nodes;						/* Array of nodes */

	CNODE			*mru_head, *mru_tail;	/* Most/Least recently used (MRU/LRU) nodes (head/tail) */
} CACHE;


extern CACHE *DataCache;					/* Data cache */
extern CACHE *ReplyCache;					/* Reply cache */

extern char *cache_status(void);
extern void cache_init(), cache_empty(CACHE *), cache_cleanup(CACHE *);
extern void *data_cache_find(uint32_t, char *, dns_qtype_t, char *, size_t);

extern int	reply_from_cache(TASK *);
extern void add_reply_to_cache(TASK *t);


#endif /* _CACHE_H */

/* vi:set ts=3: */
